# -*- coding: utf-8 -*-

"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2021/6/1 001 22:38
@Remark: 菜单模块
"""
from rest_framework import serializers
from rest_framework.decorators import action
import json

from dvadmin.system.models import Menu, MenuButton
from dvadmin.system.views.menu_button import MenuButtonSerializer
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
from dvadmin.utils.json_response import SuccessResponse, DetailResponse,ErrorResponse
from dvadmin.lowcode.models import Schema
from django.core.cache import cache
from dvadmin.utils.common import generate_unique_string
class MenuSerializer(CustomModelSerializer):
    """
    菜单表的简单序列化器
    """
    menuPermission = serializers.SerializerMethodField(read_only=True)

    def get_menuPermission(self, instance):
        queryset = instance.menuPermission.order_by('-name').values_list('name', flat=True)
        if queryset:
            return queryset
        else:
            return None

    class Meta:
        model = Menu
        fields = "__all__"
        read_only_fields = ["id"]


class MenuCreateSerializer(CustomModelSerializer):
    """
    菜单表的创建序列化器
    """
    name = serializers.CharField(required=False)

    class Meta:
        model = Menu
        fields = "__all__"
        read_only_fields = ["id"]


class MenuInitSerializer(CustomModelSerializer):
    """
    递归深度获取数信息(用于生成初始化json文件)
    """
    name = serializers.CharField(required=False)
    children = serializers.SerializerMethodField()
    menu_button = serializers.SerializerMethodField()

    def get_children(self, obj: Menu):
        data = []
        instance = Menu.objects.filter(parent_id=obj.id)
        if instance:
            serializer = MenuInitSerializer(instance=instance, many=True)
            data = serializer.data
        return data

    def get_menu_button(self, obj: Menu):
        data = []
        instance = obj.menuPermission.order_by('method')
        if instance:
            data = list(instance.values('name', 'value', 'api', 'method'))
        return data

    def save(self, **kwargs):
        instance = super().save(**kwargs)
        children = self.initial_data.get('children')
        menu_button = self.initial_data.get('menu_button')
        # 菜单表
        if children:
            for menu_data in children:
                menu_data['parent'] = instance.id
                filter_data = {
                    "name": menu_data['name'],
                    "web_path": menu_data['web_path'],
                    "component": menu_data['component'],
                    "component_name": menu_data['component_name'],
                }
                instance_obj = Menu.objects.filter(**filter_data).first()
                if instance_obj and not self.initial_data.get('reset'):
                    continue
                serializer = MenuInitSerializer(instance_obj, data=menu_data, request=self.request)
                serializer.is_valid(raise_exception=True)
                serializer.save()
        # 菜单按钮
        if menu_button:
            for menu_button_data in menu_button:
                menu_button_data['menu'] = instance.id
                filter_data = {
                    "menu": menu_button_data['menu'],
                    "value": menu_button_data['value']
                }
                instance_obj = MenuButton.objects.filter(**filter_data).first()
                serializer = MenuButtonSerializer(instance_obj, data=menu_button_data, request=self.request)
                serializer.is_valid(raise_exception=True)
                serializer.save()
        return instance

    class Meta:
        model = Menu
        fields = ['name', 'icon', 'sort', 'is_link', 'is_catalog', 'web_path', 'component', 'component_name', 'status',
                  'cache', 'visible', 'parent', 'children', 'menu_button', 'creator', 'dept_belong_id']
        extra_kwargs = {
            'creator': {'write_only': True},
            'dept_belong_id': {'write_only': True}
        }
        read_only_fields = ['id', 'children']


class WebRouterSerializer(CustomModelSerializer):
    """
    前端菜单路由的简单序列化器
    """
    path = serializers.CharField(source="web_path")
    title = serializers.CharField(source="name")
    # menuPermission = serializers.SerializerMethodField(read_only=True)
    #
    # def get_menuPermission(self, instance):
    #     # 判断是否是超级管理员
    #     if self.request.user.is_superuser:
    #         return instance.menuPermission.values_list('value', flat=True)
    #     else:
    #         # 根据当前角色获取权限按钮id集合
    #         permissionIds = self.request.user.role.values_list('permission', flat=True)
    #         queryset = instance.menuPermission.filter(id__in=permissionIds, menu=instance.id).values_list('value', flat=True)
    #         if queryset:
    #             return queryset
    #         else:
    #             return None

    class Meta:
        model = Menu
        fields = ('id', 'parent', 'icon', 'sort', 'path', 'name', 'title', 'is_link', 'is_catalog', 'web_path', 'component',
        'component_name', 'cache', 'visible','schema')
        read_only_fields = ["id"]

class PermissionSerializer(CustomModelSerializer):
    """
    前端菜单路由的简单序列化器
    """

    menuPermission = serializers.SerializerMethodField(read_only=True)

    def get_menuPermission(self, instance):
        # 判断是否是超级管理员
        if self.request.user.is_superuser:
            return instance.menuPermission.values_list('value', flat=True)
        else:
            # 根据当前角色获取权限按钮id集合
            permissionIds = self.request.user.role.values_list('permission', flat=True)
            queryset = instance.menuPermission.filter(id__in=permissionIds, menu=instance.id).values_list('value', flat=True)
            if queryset:
                return queryset
            else:
                return None

    class Meta:
        model = Menu
        fields = ('menuPermission',)
        read_only_fields = ["id"]



class NewWebRouterSerializer(CustomModelSerializer):
    """
    前端菜单路由的简单序列化器
    """
    value = serializers.IntegerField(source="id")
    label = serializers.CharField(source="name")

    class Meta:
        model = Menu
        fields = '__all__'
        fields = ('label', 'value', 'icon', 'sort','parent')
        # 'component_name', 'cache', 'visible', 'menuPermission','schema')
        # read_only_fields = ["id"]


class MenuViewSet(CustomModelViewSet):
    """
    菜单管理接口
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = Menu.objects.all()
    serializer_class = MenuSerializer
    create_serializer_class = MenuCreateSerializer
    update_serializer_class = MenuCreateSerializer
    # like查询
    search_fields = ['name', 'status','web_path','app']
    # 查询
    filter_fields = ['parent', 'name', 'status', 'is_link', 'visible', 'cache', 'is_catalog','app']
    # extra_filter_backends = []

    @action(methods=['GET'], detail=False, permission_classes=[])
    def web_router(self, request):
        """用于前端获取当前角色的路由"""
        user = request.user
        # 默认app为根目录
        path = 3
        try:
            path = request.query_params['app']
        except:
            pass
        if path == 'all':
            queryset = self.queryset.filter(status=1)
            if not user.is_superuser:
                menuIds = user.role.values_list('menu__id', flat=True)
                queryset = Menu.objects.filter(id__in=menuIds, status=1)
            serializer = WebRouterSerializer(queryset, many=True, request=request)
        else:
            queryset = self.queryset.filter(status=1,app__id=path)
            if not user.is_superuser:
                menuIds = user.role.values_list('menu__id', flat=True)
                queryset = Menu.objects.filter(id__in=menuIds, app__id=path, status=1)
            serializer = WebRouterSerializer(queryset, many=True, request=request)
        data = serializer.data
        return SuccessResponse(data=data, total=len(data), msg="获取成功")
    @action(methods=['GET'], detail=False, permission_classes=[])
    def getPermission(self, request):
        """获取权限信息"""
        user = request.user
        # 默认app为根目录
        if not user.is_superuser:
            menuIds = user.role.values_list('menu__id', flat=True)
            queryset = Menu.objects.filter(id__in=menuIds, status=1)
        else:
            queryset = self.queryset.filter(status=1)
        serializer = PermissionSerializer(queryset, many=True, request=request)
        data = serializer.data
        datas = []
        for i in data:
            if i['menuPermission']:
                datas +=(list(i['menuPermission']))
        datas = set(datas)

        return DetailResponse(data=datas, msg="获取成功")

    @action(methods=['GET'], detail=True)
    def getschema(self, request,*args, **kwargs):
        """
        /id/ 根据ID获取菜单的模板数据
        """
        instance = self.get_object()
        data = {}
        if not instance.schema:
            """如果不存在则添加数据"""
            obj = Schema.objects.get(name='home')
            objdata = Schema.objects.create(name=instance.name,schema=obj.schema,menu_id=instance.id)
            instance.schema = objdata
            instance.save()
            data = {'schema_id':instance.schema.id,'schema':json.loads(obj.schema)}
        else:
            schemadata = Schema.objects.filter(menu_id= instance.id).order_by('-create_datetime').first()
            data = {'schema_id':schemadata.id,'schema':json.loads(schemadata.schema)}
        # serializer = self.get_serializer(instance)
        """用于获取schema模板数据，如果没有则直接创建一个在返回"""
        return DetailResponse(data=data, msg="获取成功")

    @action(methods=['GET'], detail=False, permission_classes=[])
    def pathgetschema(self, request,*args, **kwargs):
        """
            通过路由路径获取相应的模板数据
        """
        data = {}

        try:
            path = request.query_params['page']
            cacheName = "{}_{}".format('schema',path )
            cachedata = cache.get(cacheName)
            if cachedata:
                return DetailResponse(data=cachedata, msg="获取成功")
            obj = Menu.objects.get(web_path="/{}".format(path))
            data = {'schema_id':obj.schema.id,'schema':json.loads(obj.schema.schema)}
            cache.set(cacheName,data,timeout=86900)
        except:
            cacheName = "{}_{}".format('schema', 'home')
            cachedata = cache.get(cacheName)
            if cachedata:
                return DetailResponse(data=cachedata, msg="获取成功")
            obj = Schema.objects.get(name='home')
            data = {'schema_id':obj.id,'schema':json.loads(obj.schema)}
            cache.set(cacheName,data, timeout=86900)
        return DetailResponse(data=data, msg="获取成功")
    @action(methods=['GET'], detail=False)
    def getrenderschema(self, request,*args, **kwargs):
        """
            通过schemaID获取相应数据
        """
        data = {}
        try:
            path = request.query_params['page']
            obj = Menu.objects.get(web_path="/{}".format(path))
            schemadata = Schema.objects.filter(menu_id= obj.id).order_by('-create_datetime').first()
            data = {'schema_id':schemadata.id,'schema':json.loads(schemadata.schema)}
        except:
            obj = Schema.objects.get(name='home')
            data = {'schema_id':obj.id,'schema':json.loads(obj.schema)}

        return DetailResponse(data=data, msg="获取成功")
    @action(methods=['GET'], detail=False, permission_classes=[])
    def treeRoutr(self, request):
        """用于前端菜单树结构树"""
        queryset = self.queryset.filter(is_catalog=True)
        serializer = NewWebRouterSerializer(queryset, many=True, request=request)
        data = serializer.data
        return SuccessResponse(data=data, total=len(data), msg="获取成功")

    def create(self, request, *args, **kwargs):
        uuid = generate_unique_string()
        request.data['uuid'] = uuid
        serializer = self.get_serializer(data=request.data, request=request)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        return DetailResponse(data=serializer.data, msg="新增成功")
    @action(methods=['GET'], detail=False)
    def uuidgetdschema(self,request):
        """
        用于公共模板同步
        """
        self.permission_classes = []
        uuid = request.query_params.get('uuid',None)
        if uuid:
            obj = self.queryset.get(uuid = uuid)
            if obj.schema:
                return DetailResponse(data=obj.schema.schema, msg="获取成功")
            return ErrorResponse(data=[], msg="不存在的数据")
        return ErrorResponse(data=[], msg="不存在的搜索字段")




